package qingyu.ai.common.speech.recognizer;

import android.content.Context;
import android.util.Log;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 语音听写
 */

public class SpeechRecognizerWrapper {
    private static volatile SpeechRecognizerWrapper mInstance;
    private SpeechRecognizer mSpeechRecognizer;
    private static final Lock locks = new ReentrantLock();
    private boolean mInited;

    private SpeechRecognizerWrapper(Context context) {
        if (mInstance != null)
            throw new RuntimeException("SpeechRecognizerWrapper can only b one instance");

        if (mSpeechRecognizer == null) {
            mSpeechRecognizer = SpeechRecognizer.createRecognizer(context, mInitListener);
            mInited = false;
        }
    }

    public static SpeechRecognizerWrapper createRecognizerCommond(Context context) {
        if (null == mInstance) {
            try {
                locks.lock();
                if (null == mInstance) {
                    mInstance = new SpeechRecognizerWrapper(context);
                }
            } finally {
                locks.unlock();
            }
        }
        return mInstance;
    }

    /**
     * 初始化参数
     * <p>
     * 由于参数后期都没有改变，可以只初始化一次
     *
     * @return
     */
    public SpeechRecognizerWrapper initRecognizerParam() {
        try {
            locks.lock();
            if (!mInited) {
                if (mSpeechRecognizer != null) {
                    mInited = true;
                    // 清空所有参数
                    mSpeechRecognizer.setParameter(SpeechConstant.PARAMS, null);
                    // 设置引擎，TYPE_CLOUD：云端，LOCAL：本地
                    mSpeechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
                    // 设置返回结果格式
                    mSpeechRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json");
                    //网络连接超时时间
                    mSpeechRecognizer.setParameter(SpeechConstant.NET_TIMEOUT, "10000");
                    //应用领域用于听写和语音语义服务,短信和日常用语：iat (默认)、视频：video、地图：poi、音乐：music
                    mSpeechRecognizer.setParameter(SpeechConstant.DOMAIN, "iat");
                    // 设置语言，zh_cn:默认简体中文
                    mSpeechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
                    // 设置语言区域,默认普通话
                    mSpeechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");
                    // 音频的采样率是音频属性的其中一个，一般来说，采样率越高音频的质量越好识别的匹配率越高，
                    mSpeechRecognizer.setParameter(SpeechConstant.SAMPLE_RATE, "16000");
                    // 设置语音前端点:开始录入音频后，音频前面部分最长静音时长。
                    mSpeechRecognizer.setParameter(SpeechConstant.VAD_BOS, "10000");
                    // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音,
                    // 这里可能会拖慢我们的反应时间
                    mSpeechRecognizer.setParameter(SpeechConstant.VAD_EOS, "1000");
                    // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
                    mSpeechRecognizer.setParameter(SpeechConstant.ASR_PTT, "0");
                    mSpeechRecognizer.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false");
                }

            }
        } finally {
            locks.unlock();
        }
        return mInstance;
    }

    /**
     * 开始录音 调用此函数，开始听写或语法识别
     * <p>
     * 此处是线程不安全，需要控制一下
     *
     * @param listener
     * @return
     */
    public void startRecognnizer(RecognizerListener listener) {
        try {
            locks.lock();
            if (!mInited) {
                initRecognizerParam();
            }
            if (mSpeechRecognizer != null && !isListener()) {
                int ret = mSpeechRecognizer.startListening(listener);
                if (ret != ErrorCode.SUCCESS) {
                    SpeechError error = new SpeechError(100, "听写失败，听写出错。");
                    listener.onError(error);
                }
            }
        } finally {
            locks.unlock();
        }

    }


    /**
     * 时间控制
     * 必须要调用createWakeUpCommond()创建,不然返回null
     *
     * @return VoiceWakeuper
     */
    public SpeechRecognizer getRecognizer(Context context) {
        return SpeechRecognizer.createRecognizer(context, mInitListener);
    }

    /**
     * 取消回话
     */
    public SpeechRecognizerWrapper cancel() {
        try {
            locks.lock();
            if (mSpeechRecognizer != null) {
                if (mSpeechRecognizer.isListening()) {
                    mSpeechRecognizer.cancel();
                }
            }
        } finally {
            locks.unlock();
        }
        return mInstance;
    }

    public boolean isListener() {
        return mSpeechRecognizer != null && mSpeechRecognizer.isListening();
    }

    /**
     * 停止语音听写，停止录音 调用本函数告知SDK，当前会话音频已全部录入。
     */
    public SpeechRecognizerWrapper stopRecognizer() {
        try {
            locks.lock();
            if (mSpeechRecognizer != null) {
                if (mSpeechRecognizer.isListening()) {
                    mSpeechRecognizer.stopListening();
                }
            }
        } finally {
            locks.unlock();
        }

        return mInstance;
    }

    public void destroy() {
        try {
            locks.lock();
            if (null != mSpeechRecognizer) {
                mSpeechRecognizer.destroy();
                mInited = false;
                mInstance = null;
            }
        } finally {
            locks.unlock();
        }
    }

    public static SpeechRecognizerWrapper getInstance() {
        return mInstance;
    }

    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            if (code != ErrorCode.SUCCESS) {
                Log.e("wfy", "Recognizer initListener failed....");
            } else {
                Log.e("wfy", "Recognizer initListener success....");
            }
        }
    };
}
